# -*- coding: utf-8 -*-

import cherrypy as _cp
from Cheetah.Template import Template 
import pymongo
from pymongo import Connection   
from pymongo.objectid import ObjectId as _id
import pymongo.json_util
import json 
import zmq 
import time
import re
from skeleton import SkeletonView
class TweetView(SkeletonView):
    
    def check_username_and_password(self, username, password): 
        user = self.db.users.find_one({'uid':username},{'uid':1,'name':1}) 
        if not user:
            return 'user(%s) not found'%username 
        _cp.session['uid'] = user['uid']
        _cp.session['uname'] = user['name']
 
    @_cp.expose
    def index(self):    
        return self.people()
    @_cp.expose
    def t(self,type=None):    
        uid = _cp.session['uid']
        tweets = self.tweet_list(uid,type)
        body = str(Template(file='www/t.html',searchList=[{
            'tweets': tweets, 
            'tweets_type':type,
        }])) 
        return self.skeleton(body)

    def logged_user_follows(self): 
        myfollows = set()
        logged_user = self.db.users.find_one({'uid':_cp.session['uid']},{'follows':1})
        if logged_user and logged_user.has_key('follows'): 
            myfollows = set(logged_user['follows'])
        return myfollows   

    @_cp.expose
    def userline(self,uid,page=0,count=16): 
        user = self.db.users.find_one({'uid':uid}) 
        tweets = self.user_tweets(uid, page, count)
        body = str(Template(file='www/userline.html',searchList=[{ 
            'uid': _cp.session['uid'],
            'uname': _cp.session['uname'], 
            'user': user,
            'tweets': tweets,
            'myfollows': self.logged_user_follows(),
        }])) 
        return self.skeleton(body)      
               
    @_cp.expose
    def people(self,orgcode=None,type=None):  
        types = []
        if not type:
            types = [u'投资顾问',u'理财顾问',u'客户经理',u'投资达人']
        else:
            types = [type]
        filter = {}
        user_groups = {}
        if orgcode: filter['org.code'] = orgcode
        for t in types:
            users = []
            filter['type'] = t
            for u in self.db.users.find(filter): users.append(u)
            user_groups[t] = users
        
        myfollows = self.logged_user_follows()
        body = str(Template(file='www/people.html',searchList=[{  
            'uid': _cp.session['uid'],                                                    
            'user_groups': user_groups,
            'group_names': types,
            'myfollows': myfollows,
        }]))   
        return self.skeleton(body) 
    
  
    @_cp.expose
    def tweet_list(self,uid,type=None):  
        logged_uid = _cp.session['uid']
        tweets,uids = [],[] 
        user = self.db.users.find_one({'uid':uid},{'follows':1})
        if user and user.has_key('follows'): uids = user['follows']
        if type:
            typed_uids = []
            for u in self.db.users.find({'uid':{'$in':uids},'type':type},{'uid':1}):
                typed_uids.append(u['uid'])
            uids = typed_uids
        else:
            uids.append(logged_uid)
        tweets = self.load_tweets(uids, 0, 16)
        return str(Template(file='www/blocks/tweet_list.html',searchList=[{ 
            'tweets': tweets, 
            'logged_uid': logged_uid,
        }]))
        
        
    def user_tweets(self,uid,page=0,count=16):
        start = page*count  
        tweets = []
        cursor = self.db.tweets.find({'user.uid':uid},{'comments':0}).sort('time',
            pymongo.DESCENDING).skip(start).limit(count)
        tweets = []
        for t in cursor: tweets.append(t) 
        for t in tweets:
            if t.has_key('retweet'):
                tid = t['retweet']
                t['retweet'] = self.db.tweets.find_one({'_id':tid},{'comments':0})
                
        return str(Template(file='www/blocks/tweet_list.html',searchList=[{ 
            'tweets': tweets,
            'logged_uid': _cp.session['uid'],
        }]))          
         
        
    
    def load_tweets(self,uids,page=0,count=16):
        start = page*count
        cursor = self.db.tweets.find({'user.uid':{'$in':uids}},{'comments':0}).sort('time',
            pymongo.DESCENDING).skip(start).limit(count)
        return self._load_tweets(cursor)
 
    def _load_tweets(self,cursor):
        tweets = []
        for t in cursor: tweets.append(t) 
        for t in tweets:
            if t.has_key('retweet'):
                tid = t['retweet']
                t['retweet'] = self.db.tweets.find_one({'_id':tid},{'comments':0})
        return tweets
    def _load_tweets_str(self,cursor):
        tweets = self._load_tweets(cursor)
        return str(Template(file='www/blocks/tweet_list.html',searchList=[{ 
            'tweets': tweets,
            'logged_uid': _cp.session['uid'],
        }]))
    
    def handle_tagging(self,text):
        text = u'%s'%text
        tags = re.findall('#(\w+\s*)#', text,re.UNICODE)
        tags = set(tags)
        for tag in tags: self.tagging(tag)
        return [tag for tag in tags]
    @_cp.expose
    def tweet(self,text,retid=None):     
        uid = _cp.session['uid']
        uname = _cp.session['uname']
        t = {
            'text': text,
            'user': {'uid':uid,'name':uname},
            'time': time.time(),
            'fav_count': 0,
            're_count': 0,
            'cmt_count': 0,
            'tags': self.handle_tagging(text),
        }
        if retid: #retweet
            retid = _id(retid)
            #retweet original tweet
            sub_ret = self.db.tweets.find_one({'_id':retid},{'retweet':1})
            if sub_ret and sub_ret.has_key('retweet'):
                retid = sub_ret['retweet']
            t['retweet'] = retid
            self.db.tweets.update({'_id':retid},{'$inc':{'re_count':1}})
        
        self.db.users.update({'uid':uid},{'$inc':{'tweets_count':1}})
        self.db.tweets.save(t)
        
        return str(Template(file='www/blocks/tweet.html',searchList=[{ 
            'logged_uid':  uid, 
            't': t,
        }]))         
    
    @_cp.expose
    def destroy(self,tid):
        uid = _cp.session['uid']
        t = self.db.tweets.find_one({'_id':_id(tid)},{'text':0})
        if t and t['user']['uid']==uid:
            self.db.tweets.remove({'_id':_id(tid)}) 
            self.db.users.update({'uid':uid},{'$inc':{'tweets_count':-1}})
            #remove comments
            self.db.comments.remove({'tid':_id(tid)})
            #if retweet, update target tweet's re_count
            if t.has_key('retweet'): 
                self.db.tweets.update({'_id':t['retweet']},{'$inc':{'re_count':-1}})
                
            
    @_cp.expose
    def comment(self,text,tid):   
        _cp.response.headers['Content-Type'] = 'application/json'
        uid = _cp.session['uid']
        uname = _cp.session['uname']
        c = {
            'text': text,
            'user': {'uid':uid,'name':uname},
            'time': time.time(),
            'tid': _id(tid), 
        } 
        self.db.comments.save(c)
        self.db.tweets.update({'_id':_id(tid)},{'$addToSet':{'comments':c['_id']},'$inc':{'cmt_count':1}})
        return json.dumps(c,default=pymongo.json_util.default)
    
    @_cp.expose
    def uncomment(self,cid,tid):  
        cid,tid = _id(cid),_id(tid)
        self.db.comments.remove({'_id':cid})
        self.db.tweets.update({'_id':tid},{'$pull':{'comments':cid},'$inc':{'cmt_count':-1}})
        
    @_cp.expose
    def comments(self,tid,page=0,count=16):   
        _cp.response.headers['Content-Type'] = 'application/json'
        page = int(page)
        count = int(count)
        start = page*count
        cursor = self.db.comments.find({'tid':_id(tid)}).skip(start).limit(count)
        cmts = []
        for c in cursor: cmts.append(c)
        return json.dumps(cmts,default=pymongo.json_util.default)
    
    @_cp.expose
    def follow(self,uid1,uid2): 
        _cp.response.headers['Content-Type'] = 'application/json'
        res = True
        try:
            if self.db.users.find_one({'uid':uid1,'follows':uid2}): 
                res = False
            else:
                self.db.users.update({'uid':uid1},{'$addToSet':{'follows':uid2},'$inc':{'follows_count':1}})
                self.db.users.update({'uid':uid2},{'$inc':{'fans_count':1}})
        except:
            res = False
        return json.dumps(res)
        
    @_cp.expose
    def unfollow(self,uid1,uid2):
        _cp.response.headers['Content-Type'] = 'application/json' 
        res = True
        try:
            if not self.db.users.find_one({'uid':uid1,'follows':uid2}): 
                res = False
            else:
                self.db.users.update({'uid':uid1},{'$pull':{'follows':uid2},'$inc':{'follows_count':-1}})
                self.db.users.update({'uid':uid2},{'$inc':{'fans_count':-1}})
        except:
            res = False
        return json.dumps(res)
            
    @_cp.expose
    def follows(self,uid,page=0,count=16):
        start = page*count
        end = start+count
        user = self.db.users.find_one({'uid':uid},{'follows':[start,end]})
        follow_ids,follow_users = [],[]
        if user and user.has_key('follows'): follow_ids = user['follows']  
        if follow_ids:
            for u in self.db.users.find({'uid':{'$in':follow_ids}}):
                follow_users.append(u)
        body = str(Template(file='www/follows.html',searchList=[{ 
            'users': follow_users,
            'uid':uid,
        }]))               
        return self.skeleton(body)
    
    @_cp.expose
    def fans(self,uid,page=0,count=16):  
        start = page*count 
        cursor = self.db.users.find({'follows':uid}).skip(start).limit(count)
        fans = []
        for user in cursor: fans.append(user)
        body = str(Template(file='www/fans.html',searchList=[{ 
            'users': fans,
            'uid': uid,
        }]))               
        return self.skeleton(body) 
    
    @_cp.expose
    def tagline(self,tag,page=0,count=16,tag_count=6):  
        tags = []
        cursor = self.db.tags.find().sort('count',pymongo.DESCENDING).limit(tag_count)
        for t in cursor: tags.append(t)
        start = page*count 
        cursor = self.db.tweets.find({'tags':tag}).skip(start).limit(count)
        body = str(Template(file='www/tagline.html',searchList=[{ 
            'tweets': self._load_tweets_str(cursor),
            'tags': tags,
            'uid': _cp.session['uid'],
            'current_tag':tag
        }]))               
        return self.skeleton(body) 
    
    def tagging(self,name):
        tag = self.db.tags.find_one({'name':name})
        if tag:
            self.db.tags.update({'name':name},{'$inc':{'count':1}})
        else:
            tag = {
                'name': name,
                'count': 1,
            }
            self.db.tags.save(tag)
    def untag(self,name):  
        tag = self.db.tags.find_one({'name':name})
        if tag.count <=1:
            self.db.tags.remove({'name':tag}) 
        else:
            self.db.tags.update({'name':name},{'$inc':{'count':-1}})   
    
    @_cp.expose
    def untag_tweet(self,tid,tag):  
        _cp.response.headers['Content-Type'] = 'application/json' 
        res = True
        try:
            self.db.tweets.update({'_id':_id(tid)},{'$pull':{'tags':tag}})
            self.db.tags.update({'name':tag},{'$inc':{'count':-1}})
        except:
            res = False
        return json.dumps(res)  
    
    @_cp.expose
    def tag_tweet(self,tid,tag):  
        _cp.response.headers['Content-Type'] = 'application/json' 
        res = None
        try:
            self.db.tweets.update({'_id':_id(tid)},{'$addToSet':{'tags':tag}})
            self.tagging(tag)
            res = self.db.tags.find_one({'name':tag})
        except:
            res = None
        return json.dumps(res,default=pymongo.json_util.default)
    
    @_cp.expose
    def toptags(self,count=16):
        tags = []
        cursor = self.db.tags.find({'count':{'$gt':0}}).sort('count',pymongo.DESCENDING).limit(count)
        for tag in cursor: tags.append(tag)
        return str(Template(file='www/blocks/tags.html',searchList=[{  
            'tags':tags,
        }]))   
    
    @_cp.expose
    def atline(self,uid,page=0,count=16): 
        pass
    
    @_cp.expose
    def favline(self,uid,page=0,count=16): 
        pass
    
    
    '''
    result status: 200 : ok, 404: not exist, 403: unauthorized
    '''
    @_cp.expose
    def check_receiver(self,recv): 
        _cp.response.headers['Content-Type'] = 'application/json'
        sender = _cp.session['uid'] 
        u_recv = self.db.users.find_one({'uid':recv},{'_id':1})
        code = 200
        if not u_recv:  code = 404
        else:
            follower = self.db.users.find_one({'uid':recv,'follows':sender},{'_id':1})
            if not follower: code = 403 
        return json.dumps(code)  
    